package com.panfeng.xcloud.common.security.feign;

import feign.Feign;
import feign.Logger;
import feign.RequestInterceptor;
import feign.codec.ErrorDecoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.http.client.Netty4ClientHttpRequestFactory;
import org.springframework.security.oauth2.client.DefaultOAuth2RequestAuthenticator;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;

/**
 * oauth2 feign 客户端调用主动配置相关bean，主要用于在feign客户端调用时传认证token信息
 *
 * @author xiaobo
 * @version 1.0
 * @since 2018-12-28
 */
@Configuration
@EnableConfigurationProperties({FeignOauth2ClientProperties.class})
public class FeignOAuth2AutoConfiguration {

    private final FeignOauth2ClientProperties oauth2ClientProperties;

    @Autowired
    public FeignOAuth2AutoConfiguration(FeignOauth2ClientProperties oauth2ClientProperties) {
        this.oauth2ClientProperties = oauth2ClientProperties;
    }

    @Bean
    public OAuth2RestTemplate oAuth2RestTemplate() {
        ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
        resourceDetails.setId(oauth2ClientProperties.getId());
        resourceDetails.setAccessTokenUri(oauth2ClientProperties.getAccessTokenUrl());
        resourceDetails.setClientId(oauth2ClientProperties.getClientId());
        resourceDetails.setClientSecret(oauth2ClientProperties.getClientSecret());

        OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(resourceDetails);
        oAuth2RestTemplate.setAuthenticator(new DefaultOAuth2RequestAuthenticator());
        oAuth2RestTemplate.setRequestFactory(new Netty4ClientHttpRequestFactory());
        return oAuth2RestTemplate;
    }

    @Bean
    public RequestInterceptor feignOAuth2RequestInterceptor() {
        return new FeignOAuth2RequestInterceptor(oAuth2RestTemplate());
    }

    @Bean
    @Scope("prototype")
    public Feign.Builder feignBuilder() {
        Feign.Builder builder = Feign.builder();
        builder.requestInterceptor(feignOAuth2RequestInterceptor());
        return builder;
    }

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    @Bean
    public ErrorDecoder errorDecoder() {
        return new FeignOauth2ErrorInterceptor();
    }
}
